#include "Scene.h"
#include "MapMgr.h"
#include "Character/monster/MonsterMgr.h"
#include "Character/monster/MonsterRefCfg.h"
#include "Character/Player.h"

#include "Character/drop/DropMgr.h"
#include "Character/npc/NpcMgr.h"
#include "Rebot/RebotMgr.h"

#include "Character/object/ObjectMgr.h"
#include "Character/newAI/behaviac/CreatureCommonAI.h"
#include "Character/CreatureMgr.h"
#include "base/core/Profiler.h"
#include "ServerModule/LogicActivityModule.h"
#include "Common/TableDataEx/MapCfg.h"

Scene::Scene()
{
	m_curGridCount = 0;
	m_updating = false;
	m_mapType = 0;
	m_mapSubType = 0;
	m_sceneId = 0;
	m_mapId = 0;
	m_sceneNoPlayerCreatures.clear();
	m_scenePlayers.clear();
	m_vecUpdate.clear();
	m_updateCount = 0;
	m_updateMax = 0;
}

Scene::~Scene()
{
}

bool Scene::Init(uint32_t mapId, uint32_t sceneId)
{
	Map *pMap = g_GetMapMgr()->GetMap(mapId);
	if (!pMap)
		return false;

	m_gridmaxHight = (uint32_t)(pMap->GetHight() / GRID_LENGTH) + 1;
	m_gridmaxWidth = (uint32_t)(pMap->GetWidth() / GRID_LENGTH) + 1;

	uint32_t w = 0;
	uint32_t h = 0;

	/*
	m_pMapGrid = new Grid* [m_gridmaxWidth];
	for (; w < m_gridmaxWidth; w++)
	{
		m_pMapGrid[w] = new Grid[m_gridmaxHight];
		for (h = 0; h < m_gridmaxHight; h++)
			m_pMapGrid[w][h].SetGridPos({ w, h });
	}
	*/
	
	m_vMapGrid.resize(m_gridmaxWidth);
	for (w = 0; w < m_gridmaxWidth; w++)
	{
		m_vMapGrid[w].resize(m_gridmaxHight);
		for (h = 0; h < m_gridmaxHight; h++)
			m_vMapGrid[w][h].SetGridPos({ w, h });
	}

	m_mapId = mapId;
	m_sceneId = sceneId;
	m_mapType = pMap->GetMapType();
	m_mapSubType = pMap->GetMapSubType();
	return true;
}

bool Scene::UnInit()
{
	/*
	for (uint32_t w = 0; w < m_gridmaxWidth; w++)
	{
		delete []m_pMapGrid[w];
		m_pMapGrid[w] = nullptr;
	}

	delete []m_pMapGrid;
	m_pMapGrid = nullptr;
	*/

	//如果还有玩家，强制切回上个场景,动态场景销毁的时候才需要做这个处理
	//if (IsDynamic())
	//{
	//	SET_UINT64 setPlayer;
	//	setPlayer.clear();
	//	MAP_UINT64_UINT32::iterator Piter = m_scenePlayerIds.begin();
	//	for (; Piter != m_scenePlayerIds.end(); Piter++)
	//	{
	//		setPlayer.insert(Piter->first);
	//	}

	//	SET_UINT64::iterator iterForce = setPlayer.begin();
	//	for (; iterForce != setPlayer.end(); ++iterForce)
	//	{
	//		uint64_t cid = (*iterForce);
	//		//主动去跟生物管理器去获取
	//		Player *pPlayer = dynamic_cast<Player*>(g_GetCreatureMgr()->GetCreature(cid));
	//		if (nullptr != pPlayer)
	//		{
	//			pPlayer->ForceReturnLastPlace();
	//		}
	//	}
	//	setPlayer.clear();
	//}


	/*SET_UINT64 setNoPlayer;
	setNoPlayer.clear();
	mapScenesNoPlayerCreatures::iterator noPlayerIter = m_sceneNoPlayerCreatures.begin();
	for (; noPlayerIter != m_sceneNoPlayerCreatures.end(); noPlayerIter++)
	{
	setNoPlayer.insert(noPlayerIter->first);
	}*/

	//以下废弃 场景不坐生物回收工作
	//Creature* pCreature = nullptr;
	//SET_UINT64::iterator iterNoPlayer = setNoPlayer.begin();
	//for (; iterNoPlayer != setNoPlayer.end(); iterNoPlayer++)
	//{
	//	pCreature = GetCreature(*iterNoPlayer);
	//	if (pCreature)
	//	{
	//		if (pCreature->CreatureKind() == CREATURE_MONSTER)
	//		{
	//			g_GetMonsterMgr()->RecyleMonster(dynamic_cast<Monster*>(pCreature));
	//		}
	//		else if (pCreature->CreatureKind() == CREATURE_SUMMON)
	//		{
	//			g_GetSummonMgr()->RecyleSummon(dynamic_cast<Summon*>(pCreature));
	//		}
	//		else if (pCreature->CreatureKind() == CREATURE_NPC)
	//		{
	//			g_GetNpcMgr()->RecyleNpc(dynamic_cast<Npc*>(pCreature));
	//		}
	//		else if (pCreature->CreatureKind() == CREATURE_DROP)
	//		{
	//			g_GetDropMgr()->RecycleDrop(dynamic_cast<Drop*>(pCreature));
	//		}
	//		else if (pCreature->CreatureKind() == CREATURE_REBOT)
	//		{
	//			g_GetRebotMgr()->RecyleRebot(dynamic_cast<CRebot*>(pCreature));
	//		}
	//		else if (pCreature->CreatureKind() == CREATURE_PET)
	//		{
	//			g_GetPetMgr()->RecylePet(dynamic_cast<CPet*>(pCreature));
	//		}
	//		else if (pCreature->CreatureKind() == CREATURE_OBJECT)
	//		{
	//			g_GetObjectMgr()->RecycleObject(dynamic_cast<Object*>(pCreature), false);
	//		}
	//		else
	//		{
	//			LogErrFmtPrint("[logic] Scene::UnInit  unkonw creature kind ...kind:%d ,sceneid:%u , mapid:%u ", pCreature->CreatureKind(),m_sceneId, m_mapId);
	//			MMO_DELETE(pCreature);
	//		}
	//	}
	//	//iter->second = nullptr; //这里需要设置为空，避免在以上物件销毁的时候又查询场景内已经销毁的物件
	//}

	//场景销毁立即销毁生物 无需等到下帧才做销毁 因为场景的销毁普通的生物无需
	/*MAP_UINT64_UINT32 mapNoPlayerCreature = m_sceneNotPlayerCreatureIds;
	MAP_UINT64_UINT32::iterator noPlayerIter = mapNoPlayerCreature.begin();
	for (; noPlayerIter != mapNoPlayerCreature.end(); noPlayerIter++)
	{
		g_GetCreatureMgr()->Destory(noPlayerIter->first);
	}*/

	//场景销毁立即销毁非玩家生物,玩家生物单独处理
	mapScenesNoPlayerCreatures::iterator noPlayerIter = m_sceneNoPlayerCreatures.begin();
	for (; noPlayerIter != m_sceneNoPlayerCreatures.end(); ++noPlayerIter)
	{
		//g_GetCreatureMgr()->WaitDestory(noPlayerIter->second->GetCid());
		//这里不能延迟销毁,场景生物身上引用了场景指针，场景是立马销毁的,而这个时候如果生物使用了自身引用的场景指针，就会崩溃
		g_GetCreatureMgr()->WaitDestory(noPlayerIter->second->GetCid());
	}

	m_sceneId = 0;
	m_scenePlayers.clear();
	m_sceneNoPlayerCreatures.clear();
	m_updating = false;

	//释放格子内存
	for (uint32_t w = 0; w < m_gridmaxWidth; w++)
	{
		for (uint32_t h = 0; h < m_gridmaxHight; h++)
		{
			m_vMapGrid[w][h].UnInit();
		}
	}

	m_gridmaxHight = 0;
	m_gridmaxWidth = 0;
	return true;
}

bool Scene::Update(uint64_t tick)
{
	m_updating = true;
	
	m_updateCount = 0;
	//场景玩家不为空的话才做场景生物更新
	//if (!IsPlayerEmpty())
	{
		//先update玩家
		mapScenesPlayers::iterator playerIter = m_scenePlayers.begin();
		for (; playerIter != m_scenePlayers.end(); ++playerIter)
		{
			if (m_updateCount >= m_updateMax) 
			{
				m_vecUpdate.push_back((Creature*)playerIter->second);
				m_updateCount++;
				m_updateMax++;
			}
			else
			{
				m_vecUpdate[m_updateCount++] = playerIter->second;
			}
		}

		//再update非玩家
//		mapScenesNoPlayerCreatures::iterator iter = m_sceneNoPlayerCreatures.begin();
//		for (; iter != m_sceneNoPlayerCreatures.end(); ++iter)
//		{
//
//			if (m_updateCount >= m_updateMax)
//			{
//				m_vecUpdate.push_back(iter->second);
//				m_updateCount++;
//				m_updateMax++;
//			}
//			else
//			{
//				m_vecUpdate[m_updateCount++] = iter->second;
//			}
//		}
	}

	for (int32_t i = 0; i < m_updateCount; i++)
	{
		if (nullptr != m_vecUpdate[i])
		{
			m_vecUpdate[i]->Update(tick);
		}
	}
	return true;
}

bool  Scene::IsDynamic() const
{
	return g_GetMapCfgMgr()->IsDynamic(m_mapId);
}

bool  Scene::IsUnion() const
{
	return g_GetMapCfgMgr()->IsUnionHomeMap(m_mapId);
}

bool  Scene::IsUnionDungeon() const
{
	return g_GetMapCfgMgr()->IsUnionDunGeonMap(m_mapId);
}

Grid* Scene::EnterScene(uint64_t Cid, Point3<float>& pos, Creature *pCreature, STransParam &transParam)
{
	uint32_t gridX = uint32_t(pos.x / GRID_LENGTH);
	uint32_t gridZ = uint32_t(pos.z / GRID_LENGTH);

	if (gridX >= m_gridmaxWidth || gridZ >= m_gridmaxHight || !pCreature)
	{
		LogErrFmtPrint("Scene::EnterScene, over max length, Cid:%lu, dstpos(%f,%f,%f,), sceneId:%d, mapId:%d gridx:%d, gridz:%d, max_x:%d, max_z:%d,transType:%d", Cid,
			pos.x, pos.y, pos.z, m_sceneId, m_mapId, gridX, gridZ, m_gridmaxWidth, m_gridmaxHight,transParam.transType);
		return nullptr;
	}

	if (g_GetSceneMgr()->IsClosed(m_sceneId))
	{
		LogDebugFmtPrint("Scene::EnterScene, scene is destorying cannt enter, Cid:%lu, dstpos(%f,%f,%f,), sceneId:%u, mapId:%u,transType:%d",
			pCreature->GetCid(), pos.x, pos.y, pos.z, m_sceneId, m_mapId, transParam.transType);
		return nullptr;
	}

	//m_pMapGrid[gridX][gridZ].AddCid(Cid);
	m_vMapGrid[gridX][gridZ].AddCreature(pCreature);

	if (pCreature->CreatureKind() != CREATURE_PLAYER)
	{
		Creature *pOldCreature = GetCreature(Cid);
		if (nullptr != pOldCreature) //这里加一条打印日志，方便定位问题
		{
			LogWarningFmtPrint("[logic] Scene::EnterScene alreday exists creature, Cid:%lu, kind:%d,enter_kind:%d, sceneid:%u, mapid:%u,transType:%d  ", Cid, pOldCreature->CreatureKind(), pCreature->CreatureKind(),m_sceneId, m_mapId,transParam.transType);
		}
		m_sceneNoPlayerCreatures[Cid] = pCreature;
	}		
	else
	{
		Player* pPlayer = dynamic_cast<Player*>(pCreature);
		if (!pPlayer)
		{
			LogErrFmtPrint("cant enter scene, switch player* error, cid:%lu,transType:%d", pCreature->GetCid(),transParam.transType);
			return nullptr;
		}
		m_scenePlayers[Cid] = pPlayer;
	}

	//有ai的话， 处理下ai
	auto pAiData = pCreature->GetAiData();
	if (pAiData)
	{
		pAiData->EnterScene(this, pos);
	}

	EnterSceneEvent enterEvent;
	enterEvent.cId = Cid;
	enterEvent.uid = pCreature->GetUid();
	enterEvent.clientId = pCreature->GetClientId();
	enterEvent.mapId = m_mapId;
	enterEvent.x = pos.x * 1000;
	enterEvent.y = pos.y * 1000;
	enterEvent.z = pos.z * 1000;
	enterEvent.transParam = transParam;
	g_GetEvent()->FireExecute(EVENT_ENTER_SCENE, m_sceneId, pCreature->CreatureKind(), &enterEvent, sizeof(enterEvent));
	g_GetEvent()->FireExecute(EVENT_CREATURE_CHANGE_SCENE, Cid, 0, &enterEvent, sizeof(enterEvent));
	//return &m_pMapGrid[gridX][gridZ];
	return &m_vMapGrid[gridX][gridZ];
}

void Scene::RemoveCreature(CharIDType Cid)
{
	mapScenesNoPlayerCreatures::iterator iter = m_sceneNoPlayerCreatures.find(Cid);
	if (iter != m_sceneNoPlayerCreatures.end())
	{
		m_sceneNoPlayerCreatures.erase(iter);
	}
	else
	{
		mapScenesPlayers::iterator playerIter = m_scenePlayers.find(Cid);
		if (playerIter != m_scenePlayers.end())
		{
			m_scenePlayers.erase(playerIter);
		}
		else
		{
			LogErrFmtPrint("Scene::LeaveScene, m_scenePlayers cannt find, cid:%lu ", Cid);
		}
	}
}

bool Scene::LeaveScene(uint64_t Cid, Grid *pGrid)
{
	if (!pGrid)
	{
		LogErrFmtPrint("Scene::LeaveScene, pgrid == nil, cid:%lu", Cid);
		return false;
	}

	//统一从生物管理器获取 先通知九宫格玩家离开
	Creature * pCreature = GetCreature(Cid);//g_GetCreatureMgr()->GetCreature(Cid);
	if (pCreature) //不可剥皮的怪物死亡，不通知客户端删除，他们自己行删除
	{

		pCreature->NoticeNineGridLeave();
		pGrid->RemoveCreature(pCreature);
	}
	else
	{
		//从场景的格子移除玩家ID
		LogErrFmtPrint("have big bug error Scene::LeaveScene pCreature==nullptr sceneId:%d, Cid:%lu", m_sceneId, Cid);
		pGrid->RemoveCid(Cid);
		return false;
	}

	RemoveCreature(Cid);

	LeaveSceneEvent leaveEvent;
	leaveEvent.cId = Cid;
	g_GetEvent()->FireExecute(EVENT_LEAVE_SCENE, m_sceneId, pCreature->CreatureKind(), &leaveEvent, sizeof(leaveEvent));
	g_GetEvent()->FireExecute(EVENT_CREATURE_CHANGE_SCENE, Cid, 0, nullptr, 0);

	return true;
}

Grid* Scene::MoveInScene(uint64_t Cid, Grid *pGrid, Point3<float>& pos, bool & isSameGrid)
{
	if (!pGrid)
		return nullptr;

	uint32_t gridX = uint32_t(pos.x / GRID_LENGTH);
	uint32_t gridZ = uint32_t(pos.z / GRID_LENGTH);
	if (gridX >= m_gridmaxWidth || gridZ >= m_gridmaxHight)
		return nullptr;

	if (pGrid->IsSame({ gridX, gridZ }))
	{
		isSameGrid = true;
		return pGrid;
	}
		
	Grid *pNewGrid = nullptr;
	//Grid *pNewGrid = &m_pMapGrid[gridX][gridZ];
	pNewGrid = &m_vMapGrid[gridX][gridZ];

	Creature * pCreature = GetCreature(Cid);//g_GetCreatureMgr()->GetCreature(Cid);
	if (pCreature)
	{
		pGrid->RemoveCreature(pCreature);
		pNewGrid->AddCreature(pCreature);
	}
	else
	{
		LogErrFmtPrint("have big bug error Scene::LeaveScene pCreature==nullptr sceneId:%d, Cid:%lu", m_sceneId, Cid);
		pGrid->RemoveCid(Cid);
	}

	isSameGrid = false;
	return pNewGrid;
}

uint32_t Scene::GetGridLayer(uint32_t gridX, uint32_t gridZ, Point3<float>& srcPos, float flength)
{
	uint32_t addGridX  = (uint32_t(srcPos.x + flength)) / GRID_LENGTH;
	uint32_t addGridZ  = (uint32_t(srcPos.z + flength)) / GRID_LENGTH;
	uint32_t reduceGridX  = (uint32_t(srcPos.x - flength)) / GRID_LENGTH;
	uint32_t reduceGridZ  = (uint32_t(srcPos.z - flength)) / GRID_LENGTH;

	uint32_t addCountX = 0;
	uint32_t reduceCountX = 0;
	uint32_t addCountZ = 0;
	uint32_t reduceCountZ = 0;
	while ((addGridX > gridX+addCountX)) addCountX++;
	while ((reduceGridX < gridX-reduceCountX)) reduceCountX++;
	while ((addGridZ > gridZ+addCountZ)) addCountZ++;
	while ((reduceGridZ < gridZ-reduceCountZ)) reduceCountZ++;

	uint32_t max_X = addCountX > reduceCountX ? addCountX : reduceCountX;
	uint32_t max_Z = addCountZ > reduceCountZ ? addCountZ : reduceCountZ;

	return max_X > max_Z ? max_X:max_Z;
}

void Scene::FindCreatureInScene(CidLst& clist, Point3<float>& srcPos, float flength, uint32_t creatureCount /* = 0 */)
{
	FindCreatureInBall(clist, srcPos, flength, creatureCount);
}

void Scene::FindCreatureInCircle(CidLst& clist, Point3<float>& srcPos, float flength, uint32_t creatureCount /* = 0 */)
{
	uint32_t gridX = uint32_t(srcPos.x / GRID_LENGTH);
	uint32_t gridZ = uint32_t(srcPos.z / GRID_LENGTH);
	uint32_t layer = GetGridLayer(gridX, gridZ, srcPos, flength);

	layer = layer > MAX_LAYER ? MAX_LAYER : layer;

	Point2<uint32_t> gridPos(gridX, gridZ);
	const vecPoint2 *pVecPoint2 = nullptr;
	for (uint32_t i = 0; i <= layer; i++)
	{
		pVecPoint2 = g_GetSceneMgr()->GetLayerPoint(i);
		if (!pVecPoint2)
		{
			LogErrFmtPrint("g_GetSceneMgr()->GetLayerPoint(i) is null, layer:%d", i);
			return;
		}
		for (uint32_t j = 0; j < pVecPoint2->size(); j++)
		{
			gridPos.x = uint32_t(gridX + pVecPoint2->at(j).x);
			gridPos.y = uint32_t(gridZ + pVecPoint2->at(j).y);
			GridCreaturesWithCircle(clist, gridPos, srcPos, flength, creatureCount);
		}
		if (creatureCount > 0 && clist.size() >= creatureCount)
			return;
	}
}

void Scene::FindCreatureInBall(CidLst& clist, Point3<float>& srcPos, float flength, uint32_t creatureCount /* = 0 */)
{
	uint32_t gridX = uint32_t(srcPos.x / GRID_LENGTH);
	uint32_t gridZ = uint32_t(srcPos.z / GRID_LENGTH);
	uint32_t layer = GetGridLayer(gridX, gridZ, srcPos, flength);

	Point2<uint32_t> gridPos(gridX, gridZ);

	for (int x = -(int)layer; x <= (int)layer; x++)
	{
		gridPos.x = gridX + x;
		for (int y = -(int)layer; y <= (int)layer; y++)
		{
			gridPos.y = gridZ + y;
			GridCreaturesWithBall(clist, gridPos, srcPos, flength, creatureCount);
		}
	}
}

void Scene::FindCreatureInSector(CidLst& clist, Point3<float>& center, Point3<float>& dir, float angle, float sectorR, uint32_t creatureCount /* = 0 */)
{
	uint32_t gridX = uint32_t(center.x / GRID_LENGTH);
	uint32_t gridZ = uint32_t(center.z / GRID_LENGTH);
	uint32_t layer = GetGridLayer(gridX, gridZ, center, sectorR);

	//float squiredR = sectorR;
	float halfAngle = (float)(double(angle/2) * 3.14159 / 180.0f);
	float cosa = cos(halfAngle);
	//Point3<float> vdir(dir.x - center.x, dir.y - center.y, dir.z - center.z);

	Point2<uint32_t> gridPos(gridX, gridZ);

	layer = layer > MAX_LAYER ? MAX_LAYER : layer;
	const vecPoint2 *pVecPoint2 = nullptr;
	for (uint32_t i = 0; i <= layer; i++)
	{
		pVecPoint2 = g_GetSceneMgr()->GetLayerPoint(i);
		if (!pVecPoint2)
		{
			LogErrFmtPrint("g_GetSceneMgr()->GetLayerPoint(i) is null, layer:%d", i);
			return;
		}
		for (uint32_t j = 0; j < pVecPoint2->size(); j++)
		{
			gridPos.x = uint32_t(gridX + pVecPoint2->at(j).x);
			gridPos.y = uint32_t(gridZ + pVecPoint2->at(j).y);
			GridCreaturesWithSector(clist, center, dir, gridPos, cosa, sectorR, creatureCount);
		}
		if (creatureCount > 0 && clist.size() >= creatureCount)
			return;
	}
}

//void Scene::FindCreatueInNineGride(Creature* pSrc, std::vector<Creature*>* clist, Point3<float> srcPos)
//{
//	uint32_t gridX = uint32_t(srcPos.x / GRID_LENGTH);
//	uint32_t gridZ = uint32_t(srcPos.z / GRID_LENGTH);
//
//	Point2<uint32_t> gridPos(gridX, gridZ);
//	const vecPoint2 *pVecPoint2 = nullptr;
//	for (uint32_t i = 0; i <= 1; i++)
//	{
//		pVecPoint2 = g_GetSceneMgr()->GetLayerPoint(i);
//		if (!pVecPoint2)
//		{
//			LogErrFmtPrint("g_GetSceneMgr()->GetLayerPoint(i) is null, layer:%d", i);
//			return;
//		}
//////////////////////////////////////先找中间的//////////////////////////////////////////////////
//		{
//			gridPos.x = uint32_t(gridX + pVecPoint2->at(0).x);
//			gridPos.y = uint32_t(gridZ + pVecPoint2->at(0).y);
//
//			if (gridPos.x >= m_gridmaxWidth || gridPos.y >= m_gridmaxHight)
//			{
//				continue;
//			}
//			Grid& mgrid = m_vMapGrid[gridPos.x][gridPos.y];
//			CidLst& gridCidlst = mgrid.GetCids();
//
//			for(auto it = gridCidlst.begin(); it != gridCidlst.end(); it++)
//			{
//				if (clist[VISION_SPECIAL_RELATIONSHIP].size() +
//						clist[VISION_LESS_FIVE_DICT].size() +
//						clist[VISION_THAN_FIVE_AND_LESS_FIFTEEN].size() >= (uint32_t)pSrc->GetVisionData().m_nineList.GetObjectCount())
//				{
//					return;
//				}
//
//				Creature* pCreature = this->GetCreature(*it);
//				if (pCreature)
//				{
//					pCreature->GetVisionData().chVisionUnitType = VISIONTYPE_NONE;
//					if (pSrc->IsSpecialRelationShip(pCreature))
//					{
//						clist[VISION_SPECIAL_RELATIONSHIP].push_back(pCreature);
//					}
//					else
//					{
//						clist[VISION_LESS_FIVE_DICT].push_back(pCreature);
//					}
//				}
//			}
//		}
//
//		bool flag = false;
//		uint32_t maxCount = 0;
//		uint32_t allCount = 0;
//		uint32_t preCount = 0;
//
//		uint32_t size = clist[VISION_SPECIAL_RELATIONSHIP].size() +
//				clist[VISION_LESS_FIVE_DICT].size() +
//				clist[VISION_THAN_FIVE_AND_LESS_FIFTEEN].size();
//
//		if (size >= (uint32_t)pSrc->GetVisionData().m_nineList.GetObjectCount())
//		{
//			return;
//		}
//
//		maxCount = pSrc->GetVisionData().m_nineList.GetObjectCount() - size;
//
//		for (uint32_t j = 0; j < pVecPoint2->size(); j++)
//		{
//			if (pVecPoint2->at(j).x == 0 && pVecPoint2->at(j).y == 0)
//			{
//				continue;
//			}
//
//			gridPos.x = uint32_t(gridX + pVecPoint2->at(j).x);
//			gridPos.y = uint32_t(gridZ + pVecPoint2->at(j).y);
//
//			if (gridPos.x >= m_gridmaxWidth || gridPos.y >= m_gridmaxHight)
//			{
//				continue;
//			}
//			Grid& mgrid = m_vMapGrid[gridPos.x][gridPos.y];
//			CidLst& gridCidlst = mgrid.GetCids();
//			allCount += gridCidlst.size();
//		}
//
//		if (maxCount < allCount)
//		{
//			flag = true;
//			preCount = allCount / 4;
//		}
//
//		for (uint32_t j = 0; j < pVecPoint2->size(); j++)
//		{
//			if (clist[VISION_SPECIAL_RELATIONSHIP].size() +
//					clist[VISION_LESS_FIVE_DICT].size() +
//					clist[VISION_THAN_FIVE_AND_LESS_FIFTEEN].size() >= (uint32_t)pSrc->GetVisionData().m_nineList.GetObjectCount())
//			{
//				return;
//			}
//
//			if (pVecPoint2->at(j).x == 0 && pVecPoint2->at(j).y == 0)
//			{
//				continue;
//			}
//
//			uint32_t useCount = 0;
//
//			gridPos.x = uint32_t(gridX + pVecPoint2->at(j).x);
//			gridPos.y = uint32_t(gridZ + pVecPoint2->at(j).y);
//
//			if (gridPos.x >= m_gridmaxWidth || gridPos.y >= m_gridmaxHight)
//			{
//				continue;
//			}
//			Grid& mgrid = m_vMapGrid[gridPos.x][gridPos.y];
//			CidLst& gridCidlst = mgrid.GetCids();
//
//			for(auto it = gridCidlst.begin(); it != gridCidlst.end(); it++)
//			{
//				if (clist[VISION_SPECIAL_RELATIONSHIP].size() +
//						clist[VISION_LESS_FIVE_DICT].size() +
//						clist[VISION_THAN_FIVE_AND_LESS_FIFTEEN].size() >= (uint32_t)pSrc->GetVisionData().m_nineList.GetObjectCount())
//				{
//					return;
//				}
//
//				Creature* pCreature = this->GetCreature(*it);
//				if (pCreature)
//				{
//					useCount++;
//					pCreature->GetVisionData().chVisionUnitType = VISIONTYPE_NONE;
//					if (pSrc->IsSpecialRelationShip(pCreature))
//					{
//						clist[VISION_SPECIAL_RELATIONSHIP].push_back(pCreature);
//					}
//					else
//					{
//						clist[VISION_THAN_FIVE_AND_LESS_FIFTEEN].push_back(pCreature);
//					}
//
//					if (flag && useCount >= preCount)
//					{
//						break;
//					}
//				}
//			}
//		}
//	}
//}

void Scene::FindDoubleSeeLstInNineGride(Creature* pSrc, std::vector<Creature*>& clist, Point3<float>& srcPos)
{
	uint32_t gridX = uint32_t(srcPos.x / GRID_LENGTH);
	uint32_t gridZ = uint32_t(srcPos.z / GRID_LENGTH);

	Point2<uint32_t> gridPos(gridX, gridZ);
	const vecPoint2 *pVecPoint2 = nullptr;
	uint8_t srcCreatureKind = pSrc->CreatureKind();
	for (uint32_t i = 0; i <= 2; i++)
	{
		pVecPoint2 = g_GetSceneMgr()->GetLayerPoint(i);
		if (!pVecPoint2)
		{
			LogErrFmtPrint("g_GetSceneMgr()->GetLayerPoint(i) is null, layer:%d", i);
			return;
		}
		for (uint32_t j = 0; j < pVecPoint2->size(); j++)
		{
			gridPos.x = uint32_t(gridX + pVecPoint2->at(j).x);
			gridPos.y = uint32_t(gridZ + pVecPoint2->at(j).y);

			if (gridPos.x >= m_gridmaxWidth || gridPos.y >= m_gridmaxHight)
			{
				continue;
			}
			Grid& mgrid = m_vMapGrid[gridPos.x][gridPos.y];
			auto& gridCidlst = mgrid.GetCids();

			for (auto pNode = gridCidlst.Head(); pNode != nullptr; pNode = gridCidlst.Next(pNode))
			{
				//CharIDType* pCid = (CharIDType*)pNode->GetHost();
				//Creature* pCreature = GetCreature(*pCid);//g_GetCreatureMgr()->GetCreature(*pCid);
				Creature* pCreature = (Creature*)pNode->GetHost();
				if (pCreature)
				{
					uint8_t dstCreatureKind = pCreature->CreatureKind();
					if (srcCreatureKind == CREATURE_PLAYER && dstCreatureKind == CREATURE_PLAYER)
					{
						continue;
					}

					if (srcCreatureKind != CREATURE_PLAYER && dstCreatureKind != CREATURE_PLAYER)
					{
						continue;
					}

					if (pCreature->GetVisionData().chVisionUnitType == VISIONTYPE_ALREADY_IN_VISION)
					{
						continue;
					}

					float dict = point2LengthSquare(srcPos, pCreature->GetPos());
					if (!pSrc->ViewFliter(pCreature, dict))
					{
						clist.push_back(pCreature);
					}
				}
			}
		}
	}
}

void Scene::FindSeeLstInNineGride(Creature* pSrc, std::vector<Creature*>* clist, Point3<float>& srcPos)
{
	uint32_t gridX = uint32_t(srcPos.x / GRID_LENGTH);
	uint32_t gridZ = uint32_t(srcPos.z / GRID_LENGTH);

	Point2<uint32_t> gridPos(gridX, gridZ);
	const vecPoint2 *pVecPoint2 = nullptr;

	//uint32_t cap = pSrc->GetVisionData().m_seeLst.GetObjectSize();
	uint32_t max = MAX_SEE_CREATURE_COUNT_IN_THE_VISION - pSrc->GetVisionData().m_doublePVPSeeLst.Count();
	float sixteenOfSightDictSquare = MAX_CHARACTER_SINGLERANGE_SQUARE / 16;
	float fourOfSightDictSquare = MAX_CHARACTER_SINGLERANGE_SQUARE / 4;
	for (uint32_t i = 0; i <= 2; i++)
	{
		pVecPoint2 = g_GetSceneMgr()->GetLayerPoint(i);
		if (!pVecPoint2)
		{
			LogErrFmtPrint("g_GetSceneMgr()->GetLayerPoint(i) is null, layer:%d", i);
			return;
		}
		for (uint32_t j = 0; j < pVecPoint2->size(); j++)
		{
			gridPos.x = uint32_t(gridX + pVecPoint2->at(j).x);
			gridPos.y = uint32_t(gridZ + pVecPoint2->at(j).y);

			if (gridPos.x >= m_gridmaxWidth || gridPos.y >= m_gridmaxHight)
			{
				continue;
			}
			Grid& mgrid = m_vMapGrid[gridPos.x][gridPos.y];
			auto& gridCidlst = mgrid.GetCids();

			for (auto pNode = gridCidlst.Head(); pNode != nullptr; pNode = gridCidlst.Next(pNode))
			{
				//CharIDType* pCid = (CharIDType*)pNode->GetHost();
				//Creature* pCreature = GetCreature(*pCid);//g_GetCreatureMgr()->GetCreature(*pCid);
				Creature* pCreature = (Creature*)pNode->GetHost();
				//如果是玩家的情况
				if (pCreature && pCreature->CreatureKind() == CREATURE_PLAYER)
				{
					if (pCreature->GetVisionData().chVisionUnitType == VISIONTYPE_ALREADY_IN_VISION)
					{
						continue;
					}

					float dict = point2LengthSquare(pSrc->GetPos(), pCreature->GetPos());
					if (!pSrc->ViewFliter(pCreature, dict))
					{
						if (dict < sixteenOfSightDictSquare)
						{
							clist[NEW_SEE_VISION_LESS_HALF_OF_HALF_MAX_SIGHT_RANGE].push_back(pCreature);
						}
						else if (dict < fourOfSightDictSquare)
						{
							clist[NEW_SEE_VISION_LESS_HALF_OF_MAX_SIGHT_RANGE].push_back(pCreature);
						}
						else
						{
							clist[NEW_SEE_VISION_THAN_HALF_OF_MAX_SIGHT_RANGE].push_back(pCreature);
						}

						if (clist[NEW_SEE_VISION_LESS_HALF_OF_HALF_MAX_SIGHT_RANGE].size() +
								clist[NEW_SEE_VISION_LESS_HALF_OF_MAX_SIGHT_RANGE].size() +
								clist[NEW_SEE_VISION_THAN_HALF_OF_MAX_SIGHT_RANGE].size() >= (uint32_t)max*5)
						{
							return;
						}
					}
				}
			}
		}
	}
}

//void Scene::FindSeeLstInNineGride(Creature* pSrc, std::vector<Creature*>* clist, Point3<float> srcPos)
//{
//	uint32_t gridX = uint32_t(srcPos.x / GRID_LENGTH);
//	uint32_t gridZ = uint32_t(srcPos.z / GRID_LENGTH);
//
//	Point2<uint32_t> gridPos(gridX, gridZ);
//	const vecPoint2 *pVecPoint2 = nullptr;
//
//	//uint32_t allVision = pSrc->GetVisionData().m_seeLst.FreeSize();
//	uint32_t allCount = 0;
//
//	for (uint32_t i = 0; i <= 1; i++)
//	{
//		pVecPoint2 = g_GetSceneMgr()->GetLayerPoint(i);
//		if (!pVecPoint2)
//		{
//			LogErrFmtPrint("g_GetSceneMgr()->GetLayerPoint(i) is null, layer:%d", i);
//			return;
//		}
//		for (uint32_t j = 0; j < pVecPoint2->size(); j++)
//		{
//			gridPos.x = uint32_t(gridX + pVecPoint2->at(j).x);
//			gridPos.y = uint32_t(gridZ + pVecPoint2->at(j).y);
//
//			if (gridPos.x >= m_gridmaxWidth || gridPos.y >= m_gridmaxHight)
//			{
//				continue;
//			}
//			Grid& mgrid = m_vMapGrid[gridPos.x][gridPos.y];
//			allCount += mgrid.GetSize();
//		}
//	}
//
//	if (allCount <= 0)
//	{
//		return;
//	}
//
//	for (uint32_t i = 0; i <= 1; i++)
//	{
//		pVecPoint2 = g_GetSceneMgr()->GetLayerPoint(i);
//		if (!pVecPoint2)
//		{
//			LogErrFmtPrint("g_GetSceneMgr()->GetLayerPoint(i) is null, layer:%d", i);
//			return;
//		}
//		for (uint32_t j = 0; j < pVecPoint2->size(); j++)
//		{
//			gridPos.x = uint32_t(gridX + pVecPoint2->at(j).x);
//			gridPos.y = uint32_t(gridZ + pVecPoint2->at(j).y);
//
//			if (gridPos.x >= m_gridmaxWidth || gridPos.y >= m_gridmaxHight)
//			{
//				continue;
//			}
//			Grid& mgrid = m_vMapGrid[gridPos.x][gridPos.y];
//			CidLst& gridCidlst = mgrid.GetCids();
//
//			uint32_t count = 0;
//			//uint32_t maxCount = allVision * mgrid.GetSize() / (float)allCount + 1;
//
//			for(auto it = gridCidlst.begin(); it != gridCidlst.end(); it++)
//			{
//				Creature* pCreature = this->GetCreature(*it);
//				if (pCreature)
//				{
//					if (pCreature->GetVisionData().chVisionUnitType == VISIONTYPE_ALREADY_IN_VISION)
//					{
//						continue;
//					}
//
//					float dict = point2LengthSquare(pSrc->GetPos(), pCreature->GetPos());
//					if (!pSrc->ViewFliter(pCreature))
//					{
//						if (dict < MAX_CHARACTER_SINGLERANGE/4.0f)
//						{
//							count++;
//							clist[NEW_SEE_VISION_LESS_HALF_OF_HALF_MAX_SIGHT_RANGE].push_back(pCreature);
//						}
//						else if (dict < MAX_CHARACTER_SINGLERANGE/2.0f)
//						{
//							count++;
//							clist[NEW_SEE_VISION_LESS_HALF_OF_MAX_SIGHT_RANGE].push_back(pCreature);
//						}
//						else
//						{
//							count++;
//							clist[NEW_SEE_VISION_THAN_HALF_OF_MAX_SIGHT_RANGE].push_back(pCreature);
//						}
//
////						if (clist[NEW_SEE_VISION_LESS_HALF_OF_HALF_MAX_SIGHT_RANGE].size() +
////								clist[NEW_SEE_VISION_LESS_HALF_OF_MAX_SIGHT_RANGE].size() +
////								clist[NEW_SEE_VISION_THAN_HALF_OF_MAX_SIGHT_RANGE].size() >= (uint32_t)pSrc->GetVisionData().m_seeLst.FreeSize()*3)
////						{
////							return;
////						}
////
////						if (count >= maxCount*3)
////						{
////							break;
////						}
//					}
//				}
//			}
//		}
//	}
//}

void Scene::FindCreatureInRect(CidLst& clist, Point3<float>& srcPos, Point3<float>& srcDir, float flength, float fwidth, uint32_t creatureCount)
{
	Point3<float> center = srcPos + srcDir * (flength / 2);
	Point3<float> dir = srcDir; // srcPos - center;
	FindCreatureInRect(clist, center, dir, srcPos, flength, fwidth, creatureCount);
}


void Scene::FindCreatureInRect(CidLst& clist, Point3<float>& center, Point3<float>& dir, Point3<float>& searchpos, float flength, float fwidth, uint32_t creatureCount /* = 0 */)
{
	uint32_t gridX = uint32_t(searchpos.x / GRID_LENGTH);
	uint32_t gridZ = uint32_t(searchpos.z / GRID_LENGTH);
	uint32_t maxLength = flength > fwidth ? flength : fwidth;
	uint32_t layer = GetGridLayer(gridX, gridZ, searchpos, maxLength);

	//Point3<float> cdir = searchpos - center;

	layer = layer > MAX_LAYER ? MAX_LAYER : layer;

	Point2<uint32_t> gridPos(gridX, gridZ);
	const vecPoint2 *pVecPoint2 = nullptr;
	for (uint32_t i = 0; i <= layer; i++)
	{
		pVecPoint2 = g_GetSceneMgr()->GetLayerPoint(i);
		if (!pVecPoint2)
		{
			LogErrFmtPrint("g_GetSceneMgr()->GetLayerPoint(i) is null, layer:%d", i);
			return;
		}
		for (uint32_t j = 0; j < pVecPoint2->size(); j++)
		{
			gridPos.x = uint32_t(gridX + pVecPoint2->at(j).x);
			gridPos.y = uint32_t(gridZ + pVecPoint2->at(j).y);
			GridCreaturesWithRect(clist, gridPos, center, dir, flength, fwidth, creatureCount);
		}
		if (creatureCount > 0 && clist.size() >= creatureCount)
			return;
	}
}

void Scene::AddRangeLstCids(CidLst& clist, Point3<float>& srcPos, Creature* pTarget, uint32_t creatureCount)
{
	if (creatureCount <= 0 || clist.size() <= creatureCount)
	{
		clist.push_back(pTarget->GetCid());
		return;
	}

	Point3<float> to   = pTarget->GetPos();
	float calculateX = (srcPos.x - to.x)*(srcPos.x - to.x);
	float calculateY = (srcPos.z - to.z)*(srcPos.z - to.z);

	uint64_t replacedCid = 0;
	float calNew = calculateX + calculateY;
	float calOld = 0;
	Creature *plistCreature = nullptr;
	CidLst::iterator iter = clist.begin();
	for (; iter != clist.end(); iter++)
	{
		plistCreature = GetCreature(*iter);//g_GetCreatureMgr()->GetCreature(*iter);
		if (!plistCreature)
		{
			replacedCid = *iter;
			clist.erase(iter);
			break;
		}
		calOld = (srcPos.x - to.x)*(srcPos.x - to.x) + (srcPos.z - to.z)*(srcPos.z - to.z);
		if (calOld > calNew)
		{
			replacedCid = *iter;
			clist.erase(iter);
			break;
		}
	}

	if (replacedCid > 0)
		clist.push_back(pTarget->GetCid());
}

void Scene::GridCreaturesWithSector(CidLst& clist, Point3<float>& center, Point3<float>& vdir, Point2<uint32_t>& gridpos, 
									float cosAngle, float squaredR, uint32_t creatureCount /* = 0 */)
{
	if (gridpos.x >= m_gridmaxWidth || gridpos.y >= m_gridmaxHight)
		return;
	//Grid mgrid = m_pMapGrid[gridpos.x][gridpos.y];
	Grid mgrid = m_vMapGrid[gridpos.x][gridpos.y];
	auto& gridCidlst = mgrid.GetCids();

	if (gridCidlst.Count() <= 0)
		return;

	for (auto pNode = gridCidlst.Head(); pNode != nullptr; pNode = gridCidlst.Next(pNode))
	{
		if (creatureCount > 0 && clist.size() >= creatureCount)
		{
			return;
		}

		//CharIDType* pCid = (CharIDType*)pNode->GetHost();
		//Creature* pCreature = GetCreature(*pCid);//g_GetCreatureMgr()->GetCreature(*pCid);
		Creature* pCreature = (Creature*)pNode->GetHost();
		if (!pCreature)
		{
			//mgrid.RemoveCid(*pCid)
			LogErrFmtPrint("Scene::GridCreaturesWithSector %p not exit in this grid(%d,%d)", pNode, gridpos.x, gridpos.y);;
			mgrid.RemoveNode(pNode);
			break;
		}
		else if (InSector(center, vdir, pCreature->GetPos(), cosAngle, squaredR+pCreature->GetModelRadius()))
			AddRangeLstCids(clist, center, pCreature, creatureCount);
	}
}

void Scene::GridCreaturesWithCircle(CidLst& clist, Point2<uint32_t>& gridpos, Point3<float>& srcPos, float flength, uint32_t creatureCount /* = 0 */)
{
	if (gridpos.x >= m_gridmaxWidth || gridpos.y >= m_gridmaxHight)
		return;
	//Grid &mgrid = m_pMapGrid[gridpos.x][gridpos.y];
	Grid &mgrid = m_vMapGrid[gridpos.x][gridpos.y];
	Point3<float> dstPos;
	auto& gridCidlst = mgrid.GetCids();

	if (gridCidlst.Count() <= 0)
		return;

	for (auto pNode = gridCidlst.Head(); pNode != nullptr; pNode = gridCidlst.Next(pNode))
	{
		if (creatureCount > 0 && clist.size() >= creatureCount)
		{
			return;
		}

		//CharIDType* pCid = (CharIDType*)pNode->GetHost();
		//Creature* pCreature = GetCreature(*pCid);//g_GetCreatureMgr()->GetCreature(*pCid);
		Creature* pCreature = (Creature*)pNode->GetHost();
		if (!pCreature)
		{
			//mgrid.RemoveCid(*pCid);
			LogErrFmtPrint("Scene::GridCreaturesWithCircle %p not exit in this grid(%d,%d)", pNode, gridpos.x, gridpos.y);
			mgrid.RemoveNode(pNode);
			break;
		}
		dstPos = pCreature->GetPos();

		if(creatureCount>0 && clist.size()>=creatureCount)
		{
			return;
		}

		if (InCircle(dstPos, srcPos, flength + pCreature->GetModelRadius()))
			AddRangeLstCids(clist, srcPos, pCreature, creatureCount);
	}
}

void Scene::GridCreaturesWithBall(CidLst& clist, Point2<uint32_t>& gridpos, Point3<float>& srcPos, float flength, uint32_t creatureCount /* = 0 */)
{
	if (gridpos.x >= m_gridmaxWidth || gridpos.y >= m_gridmaxHight)
		return;
	Grid &mgrid = m_vMapGrid[gridpos.x][gridpos.y];
	auto& gridCidlst = mgrid.GetCids();

	if (gridCidlst.Count() <= 0)
		return;

	//Creature *pCreature = nullptr;

	for (auto pNode = gridCidlst.Head(); pNode != nullptr; pNode = gridCidlst.Next(pNode))
	{
		if (creatureCount > 0 && clist.size() >= creatureCount)
		{
			return;
		}

		//CharIDType* pCid = (CharIDType*)pNode->GetHost();
		//pCreature = GetCreature(*pCid);//g_GetCreatureMgr()->GetCreature(*pCid);
		Creature *pCreature = (Creature*)pNode->GetHost();
		if (!pCreature)
		{
			LogErrFmtPrint("Scene::GridCreaturesWithBall %p not exit in this grid(%d,%d)", pNode, gridpos.x, gridpos.y);;
			mgrid.RemoveNode(pNode);
		//	mgrid.RemoveCid(*pCid);
		//	LogWarningFmtPrint("%d not exit in this grid(%d,%d)", *pCid, gridpos.x, gridpos.y);
			break;
		}
		else if (InBall(pCreature->GetPos(), srcPos, flength + pCreature->GetModelRadius()))
				AddRangeLstCids(clist, srcPos, pCreature, creatureCount);
		
	}
}

void Scene::GridCreaturesWithRect(CidLst& clist, Point2<uint32_t>& gridpos, Point3<float>& center, Point3<float>& dir, float flength, float fwidth, uint32_t creatureCount /* = 0 */)
{
	if (gridpos.x >= m_gridmaxWidth || gridpos.y >= m_gridmaxHight)
		return;
	Grid &mgrid = m_vMapGrid[gridpos.x][gridpos.y];
	auto& gridCidlst = mgrid.GetCids();

	if (gridCidlst.Count() <= 0)
		return;

	for (auto pNode = gridCidlst.Head(); pNode != nullptr; pNode = gridCidlst.Next(pNode))
	{
		if (creatureCount>0 && clist.size() >= creatureCount)
		{
			return;
		}

		Creature* pCreature = (Creature*)pNode->GetHost();
		//CharIDType* pCid = (CharIDType*)pNode->GetHost();
		//Creature* pCreature = GetCreature(*pCid);//g_GetCreatureMgr()->GetCreature(*pCid);
		if (!pCreature)
		{
			LogErrFmtPrint("Scene::GridCreaturesWithRect %p not exit in this grid(%d,%d)", pNode, gridpos.x, gridpos.y);;
			mgrid.RemoveNode(pNode);
			//mgrid.RemoveCid(*pCid);
			//LogWarningFmtPrint("%d not exit in this grid(%d,%d)", *pCid, gridpos.x, gridpos.y);
			break;
		}
		else if (InRect(pCreature->GetPos(), center, flength + pCreature->GetModelRadius(), fwidth + pCreature->GetModelRadius(), dir))
				AddRangeLstCids(clist, center, pCreature, creatureCount);
			
		
	}
}


bool Scene::InCircle(Point3<float>& from, Point3<float>& to, float flength)
{
	float calculateX = (from.x - to.x)*(from.x - to.x);
	float calculateY = 0;
	float calculateZ = (from.z - to.z)*(from.z - to.z);
	float calculate = calculateX + calculateY + calculateZ;

	return  calculate <= flength*flength;
	//return point3Length(from,to)<flength;
}

bool Scene::InBall(Point3<float>& from, Point3<float>& to, float flength)
{
	float calculateX = (from.x - to.x)*(from.x - to.x);
	float calculateY = 0;// (from.y - to.y)*(from.y - to.y);
	float calculateZ = (from.z - to.z)*(from.z - to.z);
	float calculate = calculateX + calculateY + calculateZ;

	return  calculate <= flength*flength;
	//return point3Length(from, to)<flength;
}

bool Scene::InSector(Point3<float>& center, Point3<float>& vdir, Point3<float>& targetPos, float cosAngle, float sectorR)
{
	// D = P - C
	float dx = targetPos.x - center.x;
	float dz = targetPos.z - center.z;

	float squaredR = sectorR*sectorR;
	// |D|^2 = (dx^2 + dy^2)
	float squaredLength = dx * dx + dz * dz;

	//如果两点相距比较近，则不走扇形判断
	if (abs(squaredLength)<0.5)
	{
		return true;
	}

	// |D|^2 > r^2
	if (squaredLength > squaredR+1)
		return false;

	// D dot U
	float DdotU = dx * vdir.x + dz * vdir.z;

	// D dot U > |D| cos(theta)
	// <=>
	// (D dot U)^2 > |D|^2 (cos(theta))^2 if D dot U >= 0 and cos(theta) >= 0
	// (D dot U)^2 < |D|^2 (cos(theta))^2 if D dot U <  0 and cos(theta) <  0
	// true                               if D dot U >= 0 and cos(theta) <  0
	// false                              if D dot U <  0 and cos(theta) >= 0

	//做下处理，如果相距非常近，不在这范围，也要找到他，因为玩家看起来好像在一起。
	if (DdotU > 0 && cosAngle >= 0)
	{
			return DdotU * DdotU - squaredLength * cosAngle * cosAngle >= 0;
	}
	else if (DdotU < 0 && cosAngle <= 0)
	{


		return DdotU * DdotU - squaredLength * cosAngle * cosAngle <= 0;
	}
	else
		return DdotU >= 0;
}

bool Scene::InArea(uint32_t nAreaId, Point3<float>& pos)
{
	return g_GetMapLocationCfg()->InArea(nAreaId,pos);
}

void Scene::FindPointLstInRect(Point3<float>& center, VecPoint3 &vecPos, float fwidth, float fhigh, int32_t pointCnt)
{
	if (pointCnt <= 0)
	{
		return;
	}
	Map* map = g_GetMapMgr()->GetMap(m_mapId);
	if (nullptr == map)
	{
		for (int32_t i = 0; i < pointCnt; ++i)
		{
			vecPos.push_back(center);
		}

		return;
	}
	int32_t count = 0;
	int32_t idx = 0;
	while (true)
	{
		++idx;
		if (idx >= 15)
		{
			MMOLOG_FMT_WARN("Scene::FindPointLstInRect....idx >= 15....idx:%d,fwidth:%f,fhigh:%f,pointCnt:%d ", idx, fwidth, fhigh, pointCnt);
			break;
		}
		float fcoef = idx * fwidth;
		float fcoefB = idx * fhigh;
		int32_t exnum = (idx - 1) * 2 + 1;
		Point3<float> posa(center.x - fcoef, center.y, center.z + fcoefB);
		Point3<float> posb(center.x + fcoef, center.y, center.z + fcoefB);
		Point3<float> posc(center.x + fcoef, center.y, center.z - fcoefB);
		Point3<float> posd(center.x - fcoef, center.y, center.z - fcoefB);
		//
		VecPoint3 vecTmpA;
		vecTmpA.clear();
		vecTmpA.push_back(posa);
		VecPoint3 vecTmpB;
		vecTmpB.clear();
		vecTmpB.push_back(posb);
		VecPoint3 vecTmpC;
		vecTmpC.clear();
		vecTmpC.push_back(posc);
		VecPoint3 vecTmpD;
		vecTmpD.clear();
		vecTmpD.push_back(posd);
		if (exnum > 0)
		{
			float fpera = (posb.x - posa.x) / (exnum + 1);
			float fperb = (posc.z - posb.z) / (exnum + 1);
			float fperc = (posd.x - posc.x) / (exnum + 1);
			float fperd = (posa.z - posd.z) / (exnum + 1);
			int32_t i = 1;
			for (i = 1; i < exnum; ++i)
			{
				Point3<float> tmpa(posa.x + fpera * i, posa.y, posa.z);
				Point3<float> tmpb(posb.x, posb.y, posb.z + fperb * i);
				Point3<float> tmpc(posc.x + fperc * 1, posc.y, posc.z);
				Point3<float> tmpd(posd.x, posd.y, posd.z + fperd * i);
				vecTmpA.push_back(tmpa);
				vecTmpB.push_back(tmpb);
				vecTmpC.push_back(tmpc);
				vecTmpD.push_back(tmpd);
			}
		}

		VecPoint3::iterator iterA = vecTmpA.begin();
		for (; iterA != vecTmpA.end(); ++iterA)
		{
			Point3<float> tmpPos = (*iterA);
			Point3<float> targetPos = tmpPos;
			if (map->FindNearestPos(tmpPos.x, tmpPos.z, tmpPos.y, &targetPos.x, &targetPos.z, &targetPos.y, nullptr))
			{
				vecPos.push_back(targetPos);
				++count;
				if (count >= pointCnt)
				{
					return;
				}
			}
		}

		//
		VecPoint3::iterator iterB = vecTmpB.begin();
		for (; iterB != vecTmpB.end(); ++iterB)
		{
			Point3<float> tmpPos = (*iterB);
			Point3<float> targetPos = tmpPos;
			if (map->FindNearestPos(tmpPos.x, tmpPos.z, tmpPos.y, &targetPos.x, &targetPos.z, &targetPos.y, nullptr))
			{
				vecPos.push_back(targetPos);
				++count;
				if (count >= pointCnt)
				{
					return;
				}
			}
		}

		//
		VecPoint3::iterator iterC = vecTmpC.begin();
		for (; iterC != vecTmpC.end(); ++iterC)
		{
			Point3<float> tmpPos = (*iterC);
			Point3<float> targetPos = tmpPos;
			if (map->FindNearestPos(tmpPos.x, tmpPos.z, tmpPos.y, &targetPos.x, &targetPos.z, &targetPos.y, nullptr))
			{
				vecPos.push_back(targetPos);
				++count;
				if (count >= pointCnt)
				{
					return;
				}
			}
		}
		
		//
		VecPoint3::iterator iterD = vecTmpD.begin();
		for (; iterD != vecTmpD.end(); ++iterD)
		{
			Point3<float> tmpPos = (*iterD);
			Point3<float> targetPos = tmpPos;
			if (map->FindNearestPos(tmpPos.x, tmpPos.z, tmpPos.y, &targetPos.x, &targetPos.z, &targetPos.y, nullptr))
			{
				vecPos.push_back(targetPos);
				++count;
				if (count >= pointCnt)
				{
					return;
				}
			}
		}

	} // end of while (true)
}

bool Scene::InRect(Point3<float>& position, Point3<float>& center, float length, float width, Point3<float>& dir)
{
	Point3<float> f2 = position - center;
	float totLen = sqrt(f2.x*f2.x + f2.z*f2.z);
	float dirLen = sqrt(dir.x*dir.x + dir.z*dir.z);

	

	if (dirLen < 0.000001)
	{
		return false;
	}

	//这是算出cosA  A是夹角
	float angle = ((f2.x * dir.x) + (f2.z*dir.z)) / (totLen * dirLen);
	//if (angle < 0)
	//{
	//	return false;

	//}

	//这是长判断 totlen*cosA
	float curLength = totLen * fabs(angle);
	if (curLength * 2+0.5> length)
	{
		return false;
	}

	//这是宽不超过  totlen*sinA
	float curWidth = totLen * sqrt(1 - angle * angle);
	if (curWidth * 2+0.5 > width)
	{
		return false;
	}
	return true;
}

Creature* Scene::GetCreature(uint64_t cid)
{
	//if (IsInDelMap(cid))
	//	return nullptr;

	//先从非玩家的生物列表中找
	Creature* pCreature = nullptr;
	mapScenesNoPlayerCreatures::iterator iter = m_sceneNoPlayerCreatures.find(cid);
	if (iter == m_sceneNoPlayerCreatures.end())
	{
		if (m_scenePlayers.size() > 0)
		{
			mapScenesPlayers::iterator playerIter = m_scenePlayers.find(cid);
			if (playerIter != m_scenePlayers.end())
			{
				pCreature = playerIter->second;
			}
		}
	}
	else
	{
		pCreature = iter->second;
	}

	//从统一的生物管理器去获取指针
	//return g_GetCreatureMgr()->GetCreature(cid);

	return pCreature;
}

Player* Scene::GetPlayer(CharIDType cid)
{
	mapScenesPlayers::iterator playerIter = m_scenePlayers.find(cid);
	if (playerIter != m_scenePlayers.end())
	{
		return playerIter->second;
	}
	return nullptr;
}

Drop *Scene::GetDrop(CharIDType cid)
{
	return GetCreature<Drop>(cid);
}
Monster *Scene::GetMonster(CharIDType cid)
{
	return GetCreature<Monster>(cid);
}
Npc *Scene::GetNpc(CharIDType cid)
{
	return GetCreature<Npc>(cid);
}

CRebot *Scene::GetRebot(CharIDType cid)
{
	return GetCreature<CRebot>(cid);
}

void Scene::GetAllCreatureInScene(std::vector<Creature*>& vec)
{
	mapScenesNoPlayerCreatures::iterator iter = m_sceneNoPlayerCreatures.begin();
	for (; iter != m_sceneNoPlayerCreatures.end(); ++iter)
	{
		Creature *pCreature = iter->second;//g_GetCreatureMgr()->GetCreature(iter->first);
		if (nullptr == pCreature)
		{
			continue;
		}
		vec.push_back(pCreature);
	}

	mapScenesPlayers::iterator iterPlayer = m_scenePlayers.begin();
	for (; iterPlayer != m_scenePlayers.end(); ++iterPlayer)
	{
		Creature *pCreature = iterPlayer->second;//g_GetCreatureMgr()->GetCreature(it->first);
		if (nullptr == pCreature)
		{
			continue;
		}
		vec.push_back(pCreature);
	}
}

void Scene::GetAllMonsterInScene(SET_UINT64 &setSceneMonsters)
{
	mapScenesNoPlayerCreatures::iterator iter = m_sceneNoPlayerCreatures.begin();
	for (; iter != m_sceneNoPlayerCreatures.end(); ++iter)
	{
		Creature *pCreature = iter->second;//g_GetCreatureMgr()->GetCreature(iter->first);
		if (nullptr == pCreature)
		{
			continue;
		}

		if (CREATURE_MONSTER == pCreature->CreatureKind())// && !IsInDelMap(iter->first))
		{
			setSceneMonsters.insert(iter->first);
		}
	}
}

void Scene::GetAllDropInScene(SET_UINT64 &setDrop)
{
	mapScenesNoPlayerCreatures::iterator iter = m_sceneNoPlayerCreatures.begin();
	for (; iter != m_sceneNoPlayerCreatures.end(); ++iter)
	{
		Creature *pCreature = iter->second;//g_GetCreatureMgr()->GetCreature(iter->first);
		if (nullptr == pCreature)
		{
			continue;
		}
		if (CREATURE_DROP == pCreature->CreatureKind())// && !IsInDelMap(iter->first))
		{
			setDrop.insert(iter->first);
		}
	}
}

Npc * Scene::GetNpcByCfgId(uint32_t npcCfgID)
{
	mapScenesNoPlayerCreatures::iterator iter = m_sceneNoPlayerCreatures.begin();
	for (; iter != m_sceneNoPlayerCreatures.end(); ++iter)
	{
		Creature *pCreature = iter->second;//g_GetCreatureMgr()->GetCreature(iter->first);
		if (nullptr == pCreature)
		{
			continue;
		}
		if (CREATURE_NPC == pCreature->CreatureKind())// && !IsInDelMap(iter->first))
		{
			Npc *pNpc = dynamic_cast<Npc*>(pCreature);
			if (nullptr != pNpc && npcCfgID == pNpc->GetConfigId())
			{
				return pNpc;
			}
		}
	}
	return nullptr;
}

void Scene::GetAllFightNpc(SET_UINT64 &setFightNpc)
{
	mapScenesNoPlayerCreatures::iterator iter = m_sceneNoPlayerCreatures.begin();
	for (; iter != m_sceneNoPlayerCreatures.end(); ++iter)
	{
		Creature *pCreature = iter->second;//g_GetCreatureMgr()->GetCreature(iter->first);
		if (nullptr == pCreature)
		{
			continue;
		}
		if (CREATURE_NPC == pCreature->CreatureKind())// && !IsInDelMap(iter->first))
		{
			Npc *pNpc = dynamic_cast<Npc*>(pCreature);
			if (nullptr != pNpc && pNpc->IsFightType())
			{
				setFightNpc.insert(pNpc->GetCid());
			}
		}
	}
}

Monster *Scene::GetMonsterByCfgId(uint32_t monsId)
{
	mapScenesNoPlayerCreatures::iterator iter = m_sceneNoPlayerCreatures.begin();
	for (; iter != m_sceneNoPlayerCreatures.end(); ++iter)
	{
		Creature *pCreature = iter->second;//g_GetCreatureMgr()->GetCreature(iter->first);
		if (nullptr == pCreature)
		{
			continue;
		}
		if (CREATURE_MONSTER == pCreature->CreatureKind())// && !IsInDelMap(iter->first))
		{
			Monster *pMonster = dynamic_cast<Monster*>(pCreature);
			if (nullptr != pMonster && monsId == pMonster->GetConfigId())
			{
				return pMonster;
			}
		}
	}
	return nullptr;
}

int32_t Scene::MonsNumByMasterCid(uint32_t monsId, CharIDType monsMasterCid)
{
	int32_t count = 0;
	mapScenesNoPlayerCreatures::iterator iter = m_sceneNoPlayerCreatures.begin();
	for (; iter != m_sceneNoPlayerCreatures.end(); ++iter)
	{
		Creature *pCreature = iter->second;//g_GetCreatureMgr()->GetCreature(iter->first);
		if (nullptr == pCreature)
		{
			continue;
		}
		if (CREATURE_MONSTER != pCreature->CreatureKind())// && !IsInDelMap(iter->first))
		{
			continue;
		}
		Monster *pMonster = dynamic_cast<Monster*>(pCreature);
		if (nullptr != pMonster  && monsId == pMonster->GetConfigId())
		{
			if (monsMasterCid == pMonster->GetMonsterMasterCID())
			{
				++count;
			}
		}
	}
	return count;
}


int32_t Scene::GetPlayerCount()
{
	return (int32_t)m_scenePlayers.size();
}

bool Scene::BroadCast2ClientInScene(uint32_t cmd, ProtoBufBase* buf)
{
	mapScenesPlayers::iterator iter = m_scenePlayers.begin();
	for (; iter != m_scenePlayers.end(); ++iter)
	{
		Player* pPlayer = iter->second;
		if (nullptr != pPlayer)
		{
			pPlayer->SendDataToClient(cmd, buf);
		}
		else
		{
			LogErrFmtPrint("broadcast playersInScene is error cid:%d", iter->first);
		}
	}

	return true;
}

bool Scene::BroadCast(SET_UINT64 &setChar, uint32_t module, uint32_t cmd, ProtoBufBase* buf)
{
	uint32_t clientId = 0;
	uint32_t gateId = 0;
	MAP_UINT32_LST_UINT32 gateClientsMap;

	SET_UINT64::iterator iterChar = setChar.begin();
	for (; iterChar != setChar.end(); ++iterChar)
	{
		Player *pPlayer = GetPlayer((*iterChar));
		if (nullptr != pPlayer && pPlayer->IsCanSendMessage())
		{
			pPlayer->GetGateClientId(gateId, clientId);

			LIST_UINT32& lstClientids = gateClientsMap[gateId];
			lstClientids.push_back(clientId);
		}
	}
	return g_GetLogicService()->SendDataToClient(gateClientsMap, module, cmd, buf);
}

bool Scene::BroadCast2ClientInScene(uint32_t module, uint32_t cmd, ProtoBufBase* buf)
{
	uint32_t clientId = 0;
	uint32_t gateId = 0;
	MAP_UINT32_LST_UINT32 gateClientsMap;

	mapScenesPlayers::iterator iter = m_scenePlayers.begin();
	for (; iter != m_scenePlayers.end(); ++iter)
	{
		Player* pPlayer = iter->second;//g_GetCreatureMgr()->GetPlayer(iter->first);
		if (nullptr != pPlayer)
		{
			pPlayer->GetGateClientId(gateId, clientId);

			LIST_UINT32& lstClientids = gateClientsMap[gateId];
			lstClientids.push_back(clientId);
		}
	}

	if (gateClientsMap.size() > 0)
	{
		return g_GetLogicService()->SendDataToClient(gateClientsMap, module, cmd, buf);
	}

	return false;
}

bool Scene::BroadCast2SysInScene(uint32_t cmd, ProtoBufBase* buf, uint32_t moudle /* = EMODULE_ID_SCENE */)
{
	mapScenesPlayers::iterator iter = m_scenePlayers.begin();
	for (; iter != m_scenePlayers.end(); ++iter)
	{
		Player* pPlayer = iter->second;//g_GetCreatureMgr()->GetPlayer(iter->first);
		if (nullptr != pPlayer)
		{
			g_GetLogicService()->SendDataToCenter(moudle, cmd, buf);
		}
		else
		{
			LogErrFmtPrint("broadcast sys in scene is error cid:%d", iter->first);
		}
	}
	return true;
}

bool Scene::IsInDelMap(uint64_t Cid)
{
	CidLeaveMap::iterator leave_iter = m_leaveCidMap.find(Cid);
	if (leave_iter != m_leaveCidMap.end())
		return true;
	return false;
}

void Scene::GetSrcToDstDivisionPoints(Point3<float>& from, Point3<float>& to, VecPoint3& points, float division)
{
	for (float i = 1; i <= division; i++)
	{
		Point3<float> point;
		point.x = from.x * (i / division) + to.x * (1 - i / division);
		point.y = from.y * (i / division) + to.y * (1 - i / division);
		point.z = from.z * (i / division) + to.z * (1 - i / division);
		points.push_back(point);
	}
}

bool Scene::IsSkillEffectiveArea(Point3<float>& from, Point3<float>& to, float division)
{
	Map* map = g_GetMapMgr()->GetMap(m_mapId);
	if (!map)
		return false;

	VecPoint3 points;
	GetSrcToDstDivisionPoints(from, to, points, division);

	for (uint32_t i = 0; i < points.size(); i++)
	{
		float srcPos[3] = { points[i].x, points[i].y, points[i].z };
		float nearStartPos[3];
		dtPolyRef polyRef = INVALID_NAVMESH_POLYREF;

		map->FindNearestPos(srcPos[0], srcPos[2], srcPos[1], &nearStartPos[0], &nearStartPos[2], &nearStartPos[1], &polyRef);

		uint_least16_t flags = 0;
		map->GetPolyFlags(polyRef, &flags);

		if (!(flags & SAMPLE_POLYFLAGS_WALK)) //如果不是有效区直接返回false
		{
			return false;
		}
	}

	return true;
}

bool Scene::IsPlayerEmpty()
{
	return m_scenePlayers.empty() == true;
}

void Scene::GetSameTeamPlayerIds(uint32_t teamId, LIST_INT64& clist)
{
	mapScenesPlayers::iterator iter = m_scenePlayers.begin();
	for (; iter != m_scenePlayers.end(); ++iter)
	{
		Player* pPlayer = iter->second;//g_GetCreatureMgr()->GetPlayer(iter->first);
		if (pPlayer)
		{
			if (teamId == pPlayer->GetAttr(C_TEAM_ID))
			{
				clist.push_back(iter->first);
			}
		}
	}
}

template<typename T>
T *Scene::GetCreature(CharIDType cid)
{
	Creature *pCreature = GetCreature(cid);
	if (nullptr == pCreature)
	{
		return nullptr;
	}
	return dynamic_cast<T*>(pCreature);
}
